package com.tbynet.jwp.service.impl;

import com.jfinal.aop.Inject;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.tbynet.jwp.framework.aop.Aop;
import com.tbynet.jwp.framework.core.JwpConstants;
import com.tbynet.jwp.framework.core.JwpService;
import com.tbynet.jwp.framework.bean.PageParams;
import com.tbynet.jwp.framework.exception.BusinessException;
import com.tbynet.jwp.framework.kit.StringKit;
import com.tbynet.jwp.framework.kit.ValidateKit;
import com.tbynet.jwp.service.spi.PostManager;
import com.tbynet.jwp.model.Postmeta;
import com.tbynet.jwp.model.Posts;
import com.tbynet.jwp.model.TermTaxonomy;
import com.tbynet.jwp.model.Terms;
import com.tbynet.jwp.repository.spi.*;

import java.util.*;
import java.util.function.Supplier;

/**
 * 文章管理编排层 - 优化重构版
 *
 * 核心职责：
 * 1. 文章生命周期管理（创建、更新、删除、发布）
 * 2. 分类标签关系管理
 * 3. 文章搜索和查询优化
 * 4. 缓存管理和性能优化
 *
 * 设计原则：
 * - 不包含任何SQL代码，只编排Service层方法
 * - 一个方法完成一个完整的业务用例
 * - 统一的事务管理和错误处理
 * - 支持性能监控和统计
 *
 * @author 佰亿互联
 * @version 3.1
 * @since 2025-11-04
 */
@Aop(PostManager.class)
public class PostServiceImpl extends JwpService implements PostManager {

    // ============ 业务常量 ============

    /** 默认置顶文章数量限制 */
    private static final int DEFAULT_STICKY_POST_LIMIT = 10;

    // ============ 错误码常量 ============

    /** 文章不存在错误码 */
    private static final String ERROR_POST_NOT_FOUND = "POST_NOT_FOUND";

    /** 文章不在回收站错误码 */
    private static final String ERROR_POST_NOT_IN_TRASH = "POST_NOT_IN_TRASH";

    /** 创建文章失败错误码 */
    private static final String ERROR_CREATE_POST_FAILED = "CREATE_POST_FAILED";

    /** 更新文章失败错误码 */
    private static final String ERROR_UPDATE_POST_FAILED = "UPDATE_POST_FAILED";

    /** 删除文章失败错误码 */
    private static final String ERROR_DELETE_POST_FAILED = "DELETE_POST_FAILED";

    /** 设置置顶失败错误码 */
    private static final String ERROR_SET_STICKY_FAILED = "SET_STICKY_FAILED";

    /** 批量操作失败错误码 */
    private static final String ERROR_BATCH_OPERATE_FAILED = "BATCH_OPERATE_FAILED";

    // ============ 依赖注入 ============

    @Inject
    private PostService postService;

    @Inject
    private TermService termService;

    @Inject
    private TermTaxonomyService termTaxonomyService;

    @Inject
    private TermRelationshipService termRelationshipService;

    @Inject
    private UserService userService;

    @Inject
    private CommentService commentService;

    @Inject
    private OptionService optionService;

    @Inject
    private PostCacheService postCacheService;

    @Inject
    private PostSearchService postSearchService;

    // ============ 文章生命周期管理 ============

    /**
     * 创建文章完整业务流程
     *
     * @param post 文章基本信息（必需）
     * @param postmetas 文章元数据列表（可选）
     * @param format 文章格式（可选）
     * @param categories 分类ID数组（可选）
     * @param tags 标签名称数组（可选）
     * @param sticky 是否置顶（可选）
     * @return Ret 创建结果，包含文章ID和操作状态
     *
     * @example
     * <pre>{@code
     * Posts post = new Posts();
     * post.setPostTitle("文章标题");
     * post.setPostContent("文章内容");
     *
     * List<Postmeta> metas = new ArrayList<>();
     * metas.add(new Postmeta().setMetaKey("key").setMetaValue("value"));
     *
     * Ret result = postManager.createPost(post, metas, "standard",
     *     new String[]{"1", "2"}, new String[]{"标签1", "标签2"}, true);
     * }</pre>
     */
    public Ret createPost(final Posts post, final List<Postmeta> postmetas, final String format,
                          final String[] categories, final String[] tags, final Boolean sticky) {
        return executeWithPostMonitoring("createPost", () -> {
            // 参数验证
            final Ret validationResult = validateCreatePostParams(post);
            if (validationResult.isFail()) {
                return validationResult;
            }

            // 设置默认值
            setPostDefaultValues(post);

            // 在事务中执行创建操作
            final boolean success = executeInTransaction(() ->
                    processPostCreation(post, postmetas, format, categories, tags, sticky)
            );

            return handlePostCreationResult(success, post);
        }, post != null ? String.valueOf(post.getID()) : "unknown");
    }

    /**
     * 更新文章完整业务流程
     *
     * @param post 更新后的文章信息（必需）
     * @param postmetas 更新后的元数据列表（可选）
     * @param format 文章格式（可选）
     * @param categories 分类ID数组（可选）
     * @param tags 标签名称数组（可选）
     * @param sticky 是否置顶（可选）
     * @return Ret 更新结果，包含操作状态和文章ID
     *
     * @example
     * <pre>{@code
     * Posts post = postManager.getPostDetail(1L);
     * post.setPostTitle("更新后的标题");
     *
     * Ret result = postManager.updatePost(post, null, "standard",
     *     new String[]{"3"}, new String[]{"新标签"}, false);
     * }</pre>
     */
    public Ret updatePost(final Posts post, final List<Postmeta> postmetas, final String format,
                          final String[] categories, final String[] tags, final Boolean sticky) {
        return executeWithPostMonitoring("updatePost", () -> {
            // 参数验证
            final Ret validationResult = validateUpdatePostParams(post);
            if (validationResult.isFail()) {
                return validationResult;
            }

            // 获取旧文章数据
            final Posts oldPost = getPostWithCache(post.getID());
            if (oldPost == null) {
                return buildBusinessError(ERROR_POST_NOT_FOUND, "文章不存在");
            }

            // 在事务中执行更新操作
            final boolean success = executeInTransaction(() ->
                    processPostUpdate(post, postmetas, format, categories, tags, sticky)
            );

            return handlePostUpdateResult(success, post, oldPost);
        }, post != null ? String.valueOf(post.getID()) : "unknown");
    }

    /**
     * 删除文章业务编排
     *
     * @param postId 文章ID（必需）
     * @return Ret 删除结果，包含操作状态
     *
     * @example
     * <pre>{@code
     * Ret result = postManager.deletePost(1L);
     * if (result.isOk()) {
     *     System.out.println("删除成功");
     * }
     * }</pre>
     */
    public Ret deletePost(final Object postId) {
        return executeWithPostMonitoring("deletePost", () -> {
            // 参数验证
            if (postId == null) {
                return buildParamError("postId", "文章ID不能为空");
            }

            // 验证文章存在性
            final Posts post = getPostWithCache(postId);
            if (post == null) {
                return buildBusinessError(ERROR_POST_NOT_FOUND, "文章不存在");
            }

            // 验证文章状态
            if (!Posts.POST_STATUS_TRASH.equals(post.getPostStatus())) {
                return buildBusinessError(ERROR_POST_NOT_IN_TRASH, "只能删除回收站中的文章");
            }

            // 执行删除事务
            final boolean success = executeInTransaction(() -> deletePostInTransaction(postId));

            return handlePostDeletionResult(success, postId, post);
        }, String.valueOf(postId));
    }

    // ============ 文章查询和搜索 ============

    /**
     * 搜索文章业务编排（带缓存）
     *
     * @param pageNumber 页码（必需）
     * @param pageSize 每页大小（必需）
     * @param type 文章类型（可选，默认：post）
     * @param status 文章状态（可选）
     * @param keyword 搜索关键词（可选）
     * @return Page<Posts> 搜索结果分页对象
     *
     * @example
     * <pre>{@code
     * Page<Posts> result = postManager.searchPosts(1, 20, "post", "publish", "Java");
     * List<Posts> posts = result.getList();
     * long total = result.getTotalRow();
     * }</pre>
     */
    public Page<Posts> searchPosts(final int pageNumber, final int pageSize, final String type,
                                   final String status, final String keyword) {
        if(!ValidateKit.isValidPageParams(pageNumber, pageSize)) {
            throw new BusinessException("无效的分页参数");
        }

        return executeWithPageMonitoring("searchPosts", () -> {
            // 参数验证和默认值处理
            final PageParams pageParams = PageParams.of(pageNumber, pageSize);
            final String actualType = type != null ? type : Posts.POST_TYPE_POST;

            // 生成缓存键
            final String cacheKey = postCacheService.generateSearchListCacheKey(actualType, status, keyword, null, null,
                    pageParams.getPageNumber(), pageParams.getPageSize());
            final String countCacheKey = postCacheService.generateSearchCountCacheKey(actualType, status, keyword, null, null);

            log.debug("搜索文章，关键词: %s, 缓存键: %s", StringKit.hideSensitiveInfo(keyword, 3, 3), cacheKey);

            // 尝试从缓存获取
            final Page<Posts> cachedPage = getCachedPage(cacheKey, countCacheKey, pageParams);
            if (cachedPage != null) {
                log.debug("搜索缓存命中，关键词: %s", StringKit.hideSensitiveInfo(keyword, 3, 3));
                return cachedPage;
            }

            // 缓存未命中，从数据库查询
            final Page<Posts> page = postSearchService.search(
                    pageParams.getPageNumber(), pageParams.getPageSize(), actualType, status, keyword);

            // 处理并缓存结果
            return processAndCacheSearchResult(page, cacheKey, countCacheKey, keyword);
        }, "keyword:" + (keyword != null ? StringKit.hideSensitiveInfo(keyword, 3, 3) : "null"));
    }

    /**
     * 高级搜索文章业务编排
     *
     * @param pageNumber 页码（必需）
     * @param pageSize 每页大小（必需）
     * @param type 文章类型（可选，默认：post）
     * @param status 文章状态（可选）
     * @param keyword 搜索关键词（可选）
     * @param category 分类（可选）
     * @param tag 标签（可选）
     * @param month 月份（格式：YYYYMM）（可选）
     * @param sticky 是否置顶（可选）
     * @return Page<Posts> 搜索结果分页对象
     *
     * @example
     * <pre>{@code
     * Page<Posts> result = postManager.advancedSearchPosts(1, 20, "post", "publish",
     *     "Java", "技术", "编程", "202501", true);
     * }</pre>
     */
    public Page<Posts> advancedSearchPosts(final int pageNumber, final int pageSize, final String type, final String status,
                                           final String keyword, final String category, final String tag,
                                           final String month, final Boolean sticky) {
        if(!ValidateKit.isValidPageParams(pageNumber, pageSize)) {
            throw new BusinessException("无效的分页参数");
        }

        return executeWithPageMonitoring("advancedSearchPosts", () -> {
            // 参数验证和默认值处理
            final PageParams pageParams = PageParams.of(pageNumber, pageSize);
            final String actualType = type != null ? type : Posts.POST_TYPE_POST;

            // 生成高级搜索缓存键
            final String cacheKey = postCacheService.generateAdvancedSearchListCacheKey(
                    actualType, status, keyword, category, tag, month, sticky,
                    pageParams.getPageNumber(), pageParams.getPageSize());
            final String countCacheKey = postCacheService.generateAdvancedSearchCountCacheKey(
                    actualType, status, keyword, category, tag, month, sticky);

            log.debug("高级搜索文章，参数 - 关键词: %s, 分类: %s, 标签: %s, 月份: %s, 置顶: %s",
                    StringKit.hideSensitiveInfo(keyword, 3, 3), category, tag, month, sticky);

            // 尝试从缓存获取
            final Page<Posts> cachedPage = getCachedPage(cacheKey, countCacheKey, pageParams);
            if (cachedPage != null) {
                log.debug("高级搜索缓存命中，文章数量: %s", cachedPage.getList().size());
                return cachedPage;
            }

            // 缓存未命中，从数据库查询
            final Page<Posts> page = postSearchService.advancedSearch(
                    pageParams.getPageNumber(), pageParams.getPageSize(), actualType, status,
                    keyword, category, tag, month, sticky);

            // 处理并缓存结果
            return processAndCacheAdvancedSearchResult(
                    page, cacheKey, countCacheKey, keyword, category, tag, month, sticky);
        }, "advanced_search");
    }

    /**
     * 获取文章详情业务编排（带缓存）
     *
     * @param postId 文章ID（必需）
     * @return Posts 文章详情对象，如果不存在返回null
     *
     * @example
     * <pre>{@code
     * Posts post = postManager.getPostDetail(1L);
     * if (post != null) {
     *     String title = post.getPostTitle();
     *     String content = post.getPostContent();
     * }
     * }</pre>
     */
    public Posts getPostDetail(final Object postId) {
        return executeWithPostDetailMonitoring("getPostDetail", () -> {
            // 参数验证
            if (postId == null) {
                return null;
            }

            // 尝试从缓存获取
            final Posts cachedPost = postCacheService.getPostFromCache(postId);
            if (cachedPost != null) {
                log.debug("文章详情缓存命中，文章ID: %s", postId);
                return cachedPost;
            }

            // 缓存未命中，从数据库查询并处理
            return processAndCachePostDetail(postId);
        }, String.valueOf(postId));
    }

    // ============ 置顶文章管理 ============

    /**
     * 获取置顶文章列表业务编排
     *
     * @return List<Posts> 置顶文章列表，如果没有置顶文章返回空列表
     *
     * @example
     * <pre>{@code
     * List<Posts> stickyPosts = postManager.getStickyPosts();
     * for (Posts post : stickyPosts) {
     *     System.out.println(post.getPostTitle());
     * }
     * }</pre>
     */
    public List<Posts> getStickyPosts() {
        return executeWithListMonitoring("getStickyPosts", () -> {
            // 获取置顶文章ID列表
            final List<Integer> stickyIds = optionService.getStickyPosts();
            if (stickyIds.isEmpty()) {
                log.debug("没有置顶文章");
                return new ArrayList<>();
            }

            // 获取文章详情并补充信息
            return getPostsByIdsWithEnrichment(convertToObjectList(stickyIds));
        }, "sticky_posts");
    }

    /**
     * 检查文章是否置顶
     *
     * @param postId 文章ID（必需）
     * @return boolean 如果文章置顶返回true，否则返回false
     *
     * @example
     * <pre>{@code
     * boolean isSticky = postManager.isStickyPost(1L);
     * if (isSticky) {
     *     System.out.println("文章已置顶");
     * }
     * }</pre>
     */
    public boolean isStickyPost(final Object postId) {
        return optionService.isStickyPost(postId);
    }

    /**
     * 设置文章置顶状态业务编排
     *
     * @param postId 文章ID（必需）
     * @param sticky 是否置顶（必需）
     * @return Ret 操作结果，包含操作状态
     *
     * @example
     * <pre>{@code
     * // 置顶文章
     * Ret result1 = postManager.setSticky(1L, true);
     *
     * // 取消置顶
     * Ret result2 = postManager.setSticky(1L, false);
     * }</pre>
     */
    public Ret setSticky(final Object postId, final boolean sticky) {
        return executeWithPostMonitoring("setSticky", () -> {
            // 参数验证
            if (postId == null) {
                return buildParamError("postId", "文章ID不能为空");
            }

            // 验证文章存在性
            if (!validatePostExists(postId)) {
                return buildBusinessError(ERROR_POST_NOT_FOUND, "文章不存在");
            }

            final boolean success = sticky ?
                    optionService.addStickyPost(postId) : optionService.removeStickyPost(postId);

            return handleStickyOperationResult(success, postId, sticky);
        }, String.valueOf(postId));
    }

    /**
     * 批量设置置顶状态业务编排
     *
     * @param postIds 文章ID列表（必需）
     * @param sticky 是否置顶（必需）
     * @return Ret 操作结果，包含操作状态
     *
     * @example
     * <pre>{@code
     * List<Object> postIds = Arrays.asList(1L, 2L, 3L);
     * Ret result = postManager.batchSetSticky(postIds, true);
     * }</pre>
     */
    public Ret batchSetSticky(final List<Object> postIds, final boolean sticky) {
        return executeWithBatchMonitoring("batchSetSticky", () -> {
            // 参数验证
            if (!validateBatchOperationParams(postIds)) {
                return buildParamError("postIds", "文章ID列表不能为空");
            }

            final boolean success = executeInTransaction(() -> processBatchStickyOperation(postIds, sticky));

            return handleBatchStickyResult(success, postIds.size(), sticky);
        }, "sticky:" + sticky);
    }

    // ============ 批量操作管理 ============

    /**
     * 批量操作文章业务编排
     *
     * @param postIds 文章ID数组（必需）
     * @param action 操作类型（必需，可选值：trash|delete|restore）
     * @return Ret 操作结果，包含操作状态
     *
     * @example
     * <pre>{@code
     * // 移至回收站
     * Ret result1 = postManager.batchOperatePosts(new String[]{"1", "2"}, "trash");
     *
     * // 永久删除
     * Ret result2 = postManager.batchOperatePosts(new String[]{"1", "2"}, "delete");
     *
     * // 从回收站恢复
     * Ret result3 = postManager.batchOperatePosts(new String[]{"1", "2"}, "restore");
     * }</pre>
     */
    public Ret batchOperatePosts(final String[] postIds, final String action) {
        return executeWithBatchMonitoring("batchOperatePosts", () -> {
            // 参数验证
            if (!validateBatchOperationParams(postIds)) {
                return buildParamError("postIds", "请选择要操作的文章");
            }

            final boolean success = executeInTransaction(() -> processBatchOperation(postIds, action));

            return handleBatchOperationResult(success, action, postIds.length);
        }, action);
    }

    // ============ 私有方法：执行模板 ============

    /**
     * 执行文章操作并监控（返回Ret类型）
     */
    private Ret executeWithPostMonitoring(final String methodName, final Supplier<Ret> operation, final String identifier) {
        return executeWithMonitoring(methodName, operation, identifier,
                e -> buildBusinessError(getErrorCode(methodName), getErrorMessage(methodName)));
    }

    /**
     * 执行分页操作并监控（返回Page类型）
     */
    private Page<Posts> executeWithPageMonitoring(final String methodName, final Supplier<Page<Posts>> operation, final String identifier) {
        return executeWithMonitoring(methodName, operation, identifier,
                e -> new Page<>(Collections.emptyList(), 1, 10, 0, 0));
    }

    /**
     * 执行列表操作并监控（返回List类型）
     */
    private List<Posts> executeWithListMonitoring(final String methodName, final Supplier<List<Posts>> operation, final String identifier) {
        return executeWithMonitoring(methodName, operation, identifier,
                e -> new ArrayList<>());
    }

    /**
     * 执行文章详情操作并监控（返回Posts类型）
     */
    private Posts executeWithPostDetailMonitoring(final String methodName, final Supplier<Posts> operation, final String identifier) {
        return executeWithMonitoring(methodName, operation, identifier,
                e -> null);
    }

    /**
     * 执行批量操作并监控（返回Ret类型）
     */
    private Ret executeWithBatchMonitoring(final String methodName, final Supplier<Ret> operation, final String identifier) {
        return executeWithMonitoring(methodName, operation, identifier,
                e -> buildBusinessError(ERROR_BATCH_OPERATE_FAILED, "批量操作失败"));
    }

    /**
     * 通用执行监控模板
     */
    private <T> T executeWithMonitoring(final String methodName, final Supplier<T> operation,
                                        final String identifier, final java.util.function.Function<Exception, T> errorHandler) {
        final long startTime = System.currentTimeMillis();
        try {
            recordMethodCall(methodName);
            final T result = operation.get();
            logMethodPerformance(methodName, startTime, "SUCCESS");
            return result;
        } catch (Exception e) {
            recordMethodError(methodName);
            log.error("%s异常，标识: %s", methodName, identifier, e);
            return errorHandler.apply(e);
        }
    }

    // ============ 私有方法：参数验证 ============

    /**
     * 验证创建文章参数
     */
    private Ret validateCreatePostParams(final Posts post) {
        if (post == null) {
            return buildParamError("post", "文章信息不能为空");
        }
        if (StrKit.isBlank(post.getPostTitle())) {
            return buildParamError("postTitle", "文章标题不能为空");
        }
        if (StrKit.isBlank(post.getPostContent())) {
            return buildParamError("postContent", "文章内容不能为空");
        }
        return buildSuccess("参数验证通过", null);
    }

    /**
     * 验证更新文章参数
     */
    private Ret validateUpdatePostParams(final Posts post) {
        if (post == null || post.getID() == null) {
            return buildParamError("post", "文章信息和文章ID不能为空");
        }
        if (StrKit.isBlank(post.getPostTitle())) {
            return buildParamError("postTitle", "文章标题不能为空");
        }
        if (StrKit.isBlank(post.getPostContent())) {
            return buildParamError("postContent", "文章内容不能为空");
        }
        return buildSuccess("参数验证通过", null);
    }

    /**
     * 验证批量操作参数
     */
    private boolean validateBatchOperationParams(final List<Object> postIds) {
        return postIds != null && !postIds.isEmpty() && postIds.size() <= JwpConstants.MAX_BATCH_OPERATION_SIZE;
    }

    /**
     * 验证批量操作参数
     */
    private boolean validateBatchOperationParams(final String[] postIds) {
        return postIds != null && postIds.length > 0 && postIds.length <= JwpConstants.MAX_BATCH_OPERATION_SIZE;
    }

    // ============ 私有方法：数据构建和默认值 ============

    /**
     * 设置文章默认值
     */
    private void setPostDefaultValues(final Posts post) {
        if (post.getPostDate() == null) {
            post.setPostDate(new Date());
        }
        if (post.getPostModified() == null) {
            post.setPostModified(new Date());
        }
        if (StrKit.isBlank(post.getPostStatus())) {
            post.setPostStatus(Posts.POST_STATUS_DRAFT);
        }
        if (StrKit.isBlank(post.getPostType())) {
            post.setPostType(Posts.POST_TYPE_POST);
        }
        if (StrKit.isBlank(post.getCommentStatus())) {
            post.setCommentStatus(Posts.COMMENT_STATUS_OPEN);
        }
        if (StrKit.isBlank(post.getPingStatus())) {
            post.setPingStatus(Posts.PING_STATUS_OPEN);
        }
    }

    // ============ 私有方法：业务处理核心 ============

    /**
     * 处理文章创建流程
     */
    private boolean processPostCreation(final Posts post, final List<Postmeta> postmetas, final String format,
                                        final String[] categories, final String[] tags, final Boolean sticky) {
        return executeAll(
                () -> savePostBasicInfo(post),
                () -> savePostMetas(post.getID(), postmetas),
                () -> savePostCategories(post.getID(), categories),
                () -> savePostTags(post.getID(), tags),
                () -> savePostFormat(post.getID(), format),
                () -> handleStickyStatus(post.getID(), sticky)
        );
    }

    /**
     * 处理文章更新流程
     */
    private boolean processPostUpdate(final Posts post, final List<Postmeta> postmetas, final String format,
                                      final String[] categories, final String[] tags, final Boolean sticky) {
        return executeAll(
                () -> updatePostBasicInfo(post),
                () -> updatePostMetas(post.getID(), postmetas),
                () -> updatePostCategories(post.getID(), categories),
                () -> updatePostTags(post.getID(), tags),
                () -> updatePostFormat(post.getID(), format),
                () -> updateStickyStatus(post.getID(), sticky)
        );
    }

    /**
     * 在事务中删除文章
     */
    private boolean deletePostInTransaction(final Object postId) {
        return executeAll(
                () -> postService.deletePostMetas(postId),
                () -> deleteAllPostRelationships(postId),
                () -> postService.deleteById(postId)
        );
    }

    /**
     * 执行所有操作，全部成功返回true
     */
    @SafeVarargs
    private final boolean executeAll(final Supplier<Boolean>... operations) {
        for (final Supplier<Boolean> operation : operations) {
            if (!operation.get()) {
                return false;
            }
        }
        return true;
    }

    // ============ 私有方法：Service层调用封装 ============

    private boolean savePostBasicInfo(final Posts post) {
        return postService.save(post);
    }

    private boolean updatePostBasicInfo(final Posts post) {
        return postService.update(post);
    }

    private boolean savePostMetas(final Object postId, final List<Postmeta> postmetas) {
        return postmetas == null || postmetas.isEmpty() || postService.savePostMetas(postId, postmetas);
    }

    private boolean updatePostMetas(final Object postId, final List<Postmeta> postmetas) {
        return postService.updatePostMetas(postId, postmetas);
    }

    private boolean savePostCategories(final Object postId, final String[] categories) {
        return categories == null || categories.length == 0 ||
                Arrays.stream(categories).allMatch(categoryId -> saveSingleCategory(postId, categoryId));
    }

    private boolean saveSingleCategory(final Object postId, final String categoryId) {
        final TermTaxonomy taxonomy = termTaxonomyService.getTermTaxonomy(categoryId, TermTaxonomy.TAXONOMY_CATEGORY);
        return taxonomy != null && termRelationshipService.saveTermRelationship(postId, taxonomy.getTermTaxonomyId());
    }

    private boolean savePostTags(final Object postId, final String[] tags) {
        return tags == null || tags.length == 0 ||
                Arrays.stream(tags).filter(StrKit::notBlank).allMatch(tag -> saveSingleTag(postId, tag));
    }

    private boolean saveSingleTag(final Object postId, final String tag) {
        final Terms term = termService.getOrCreateTerm(tag, TermTaxonomy.TAXONOMY_POST_TAG);
        if (term == null) {
            return false;
        }

        final TermTaxonomy taxonomy = termTaxonomyService.getOrCreateTermTaxonomy(term.getTermId(), TermTaxonomy.TAXONOMY_POST_TAG);
        return taxonomy != null && termRelationshipService.saveTermRelationship(postId, taxonomy.getTermTaxonomyId());
    }

    private boolean savePostFormat(final Object postId, final String format) {
        if (format == null || "0".equals(format)) {
            return true;
        }

        final String name = "post-format-" + format;
        final Terms term = termService.getOrCreateTerm(name, TermTaxonomy.TAXONOMY_POST_FORMAT);
        if (term == null) {
            return false;
        }

        final TermTaxonomy taxonomy = termTaxonomyService.getOrCreateTermTaxonomy(term.getTermId(), TermTaxonomy.TAXONOMY_POST_FORMAT);
        return taxonomy != null && termRelationshipService.saveTermRelationship(postId, taxonomy.getTermTaxonomyId());
    }

    private boolean handleStickyStatus(final Object postId, final Boolean sticky) {
        return sticky == null || !sticky || optionService.addStickyPost(postId);
    }

    private boolean updateStickyStatus(final Object postId, final Boolean sticky) {
        return sticky == null || (sticky ? optionService.addStickyPost(postId) : optionService.removeStickyPost(postId));
    }

    private boolean updatePostCategories(final Object postId, final String[] categories) {
        return termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_CATEGORY) &&
                savePostCategories(postId, categories);
    }

    private boolean updatePostTags(final Object postId, final String[] tags) {
        return termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_POST_TAG) &&
                savePostTags(postId, tags);
    }

    private boolean updatePostFormat(final Object postId, final String format) {
        return termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_POST_FORMAT) &&
                savePostFormat(postId, format);
    }

    private boolean deleteAllPostRelationships(final Object postId) {
        return termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_CATEGORY) &&
                termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_POST_TAG) &&
                termRelationshipService.deletePostTermRelationships(postId, TermTaxonomy.TAXONOMY_POST_FORMAT);
    }

    // ============ 私有方法：批量操作处理 ============

    private boolean processBatchOperation(final String[] postIds, final String action) {
        switch (action) {
            case "trash":
                return batchMoveToTrash(postIds);
            case "delete":
                return batchDelete(postIds);
            case "restore":
                return batchRestore(postIds);
            default:
                log.error("不支持的批量操作类型: %s", action);
                return false;
        }
    }

    private boolean batchMoveToTrash(final String[] postIds) {
        return Arrays.stream(postIds)
                .map(postId -> {
                    final Posts post = postService.getById(postId);
                    if (post != null) {
                        post.setPostStatus(Posts.POST_STATUS_TRASH);
                        return postService.update(post);
                    }
                    return true;
                })
                .allMatch(result -> result);
    }

    private boolean batchRestore(final String[] postIds) {
        return Arrays.stream(postIds)
                .map(postId -> {
                    final Posts post = postService.getById(postId);
                    if (post != null && Posts.POST_STATUS_TRASH.equals(post.getPostStatus())) {
                        post.setPostStatus(Posts.POST_STATUS_DRAFT);
                        return postService.update(post);
                    }
                    return true;
                })
                .allMatch(result -> result);
    }

    private boolean batchDelete(final String[] postIds) {
        return Arrays.stream(postIds).allMatch(this::deletePostInTransaction);
    }

    private boolean processBatchStickyOperation(final List<Object> postIds, final boolean sticky) {
        return postIds.stream()
                .map(postId -> sticky ? optionService.addStickyPost(postId) : optionService.removeStickyPost(postId))
                .allMatch(result -> result);
    }

    // ============ 私有方法：缓存管理 ============

    private Page<Posts> getCachedPage(final String cacheKey, final String countCacheKey, final PageParams pageParams) {
        final List<Posts> cachedPosts = postCacheService.getPostListFromCache(cacheKey);
        final Long cachedTotalRow = postCacheService.getPostCountFromCache(countCacheKey);

        if (cachedPosts != null && cachedTotalRow != null) {
            final int totalPage = (int) Math.ceil((double) cachedTotalRow / pageParams.getPageSize());
            return new Page<>(cachedPosts, pageParams.getPageNumber(), pageParams.getPageSize(),
                    totalPage, cachedTotalRow.intValue());
        }
        return null;
    }

    private Page<Posts> processAndCacheSearchResult(final Page<Posts> page, final String cacheKey,
                                                    final String countCacheKey, final String keyword) {
        // 补充文章额外信息
        page.getList().forEach(this::enrichPostInfo);

        // 异步缓存结果
        cachePageResult(page, cacheKey, countCacheKey, "缓存搜索结果");
        return page;
    }

    private Page<Posts> processAndCacheAdvancedSearchResult(final Page<Posts> page, final String cacheKey,
                                                            final String countCacheKey, final String keyword,
                                                            final String category, final String tag, final String month,
                                                            final Boolean sticky) {
        // 补充文章额外信息
        page.getList().forEach(this::enrichPostInfo);

        // 异步缓存结果
        cachePageResult(page, cacheKey, countCacheKey, "缓存高级搜索结果");
        return page;
    }

    private void cachePageResult(final Page<Posts> page, final String cacheKey,
                                 final String countCacheKey, final String taskName) {
        if (page.getList() != null && !page.getList().isEmpty()) {
            executeAsync(() -> {
                postCacheService.putPostListToCache(cacheKey, page.getList());
                postCacheService.putPostCountToCache(countCacheKey, page.getTotalRow());
            }, taskName);
        }
    }

    private Posts processAndCachePostDetail(final Object postId) {
        final Posts post = postService.getById(postId);
        if (post != null) {
            enrichPostInfo(post);
            executeAsync(() -> postCacheService.putPostToCache(post), "缓存文章详情");
        }
        return post;
    }

    private void enrichPostInfo(final Posts post) {
        try {
            final Object postId = post.getID();
            post.put("sticky", optionService.isStickyPost(postId));
            post.put("categories", termService.getTerms(postId, TermTaxonomy.TAXONOMY_CATEGORY));
            post.put("tags", termService.getTerms(postId, TermTaxonomy.TAXONOMY_POST_TAG));
            post.put("author", userService.getById(post.getPostAuthor()));
            post.put("comments", commentService.countByPostId(postId));
        } catch (Exception e) {
            log.error("丰富文章信息异常，文章ID: %s", post.getID(), e);
        }
    }

    // ============ 私有方法：结果处理 ============

    private Ret handlePostCreationResult(final boolean success, final Posts post) {
        if (success) {
            executeAsync(() -> clearPostRelatedCache(post), "清理文章缓存");
            return buildSuccess("创建文章成功", Ret.by("postId", post.getID()));
        } else {
            return buildBusinessError(ERROR_CREATE_POST_FAILED, "创建文章失败");
        }
    }

    private Ret handlePostUpdateResult(final boolean success, final Posts newPost, final Posts oldPost) {
        if (success) {
            executeAsync(() -> {
                clearPostRelatedCache(newPost);
                triggerPostUpdateEvent(oldPost, newPost);
            }, "文章更新后处理");
            return buildSuccess("更新文章成功", Ret.by("postId", newPost.getID()));
        } else {
            return buildBusinessError(ERROR_UPDATE_POST_FAILED, "更新文章失败");
        }
    }

    private Ret handlePostDeletionResult(final boolean success, final Object postId, final Posts post) {
        if (success) {
            executeAsync(() -> {
                clearPostCache(postId);
                triggerPostDeleteEvent(postId, post);
            }, "文章删除后处理");
            return buildSuccess("删除文章成功", null);
        } else {
            return buildBusinessError(ERROR_DELETE_POST_FAILED, "删除文章失败");
        }
    }

    private Ret handleStickyOperationResult(final boolean success, final Object postId, final boolean sticky) {
        if (success) {
            executeAsync(() -> clearPostCache(postId), "清理置顶文章缓存");
            return buildSuccess(sticky ? "置顶成功" : "取消置顶成功", null);
        } else {
            return buildBusinessError(ERROR_SET_STICKY_FAILED, sticky ? "置顶失败" : "取消置顶失败");
        }
    }

    private Ret handleBatchStickyResult(final boolean success, final int count, final boolean sticky) {
        if (success) {
            executeAsync(this::clearAllPostCache, "清理批量置顶缓存");
            return buildSuccess(sticky ? "批量置顶成功" : "批量取消置顶成功", null);
        } else {
            return buildBusinessError(ERROR_BATCH_OPERATE_FAILED, sticky ? "批量置顶失败" : "批量取消置顶失败");
        }
    }

    private Ret handleBatchOperationResult(final boolean success, final String action, final int count) {
        if (success) {
            executeAsync(this::clearAllPostCache, "清理批量操作缓存");
            return buildSuccess(getBatchOperationMessage(action), null);
        } else {
            return buildBusinessError(ERROR_BATCH_OPERATE_FAILED, "操作失败");
        }
    }

    // ============ 私有方法：缓存清理 ============

    private void clearPostRelatedCache(final Posts post) {
        if (post == null) {
            return;
        }
        clearPostCache(post.getID());
        if (post.getPostTitle() != null) {
            postCacheService.clearSearchCache(post.getPostTitle());
        }
        clearAllPostCache();
    }

    private void clearPostCache(final Object postId) {
        postCacheService.removePostFromCache(postId);
    }

    private void clearAllPostCache() {
        postCacheService.clearAllPostCache();
    }

    // ============ 私有方法：事件触发 ============

    private void triggerPostUpdateEvent(final Posts oldPost, final Posts newPost) {
        executeAsync(() -> logPostChange(oldPost, newPost), "文章更新事件");
    }

    private void triggerPostDeleteEvent(final Object postId, final Posts post) {
        executeAsync(() -> logPostDeletion(postId, post), "文章删除事件");
    }

    private void logPostChange(final Posts oldPost, final Posts newPost) {
        final List<String> changes = new ArrayList<>();
        if (!Objects.equals(oldPost.getPostTitle(), newPost.getPostTitle())) {
            changes.add("标题: " + StringKit.hideSensitiveInfo(oldPost.getPostTitle(), 5, 5) +
                    " -> " + StringKit.hideSensitiveInfo(newPost.getPostTitle(), 5, 5));
        }
        if (!Objects.equals(oldPost.getPostStatus(), newPost.getPostStatus())) {
            changes.add("状态: " + oldPost.getPostStatus() + " -> " + newPost.getPostStatus());
        }
        if (!changes.isEmpty()) {
            log.info("文章信息变更，文章ID: %s, 变更内容: %s", newPost.getID(), String.join("; ", changes));
        }
    }

    private void logPostDeletion(final Object postId, final Posts post) {
        log.info("文章已被删除，文章ID: %s, 标题: %s, 删除时间: %s",
                postId, post != null ? StringKit.hideSensitiveInfo(post.getPostTitle(), 5, 5) : "unknown", new Date());
    }

    // ============ 私有方法：工具方法 ============

    private boolean validatePostExists(final Object postId) {
        return postService.getById(postId) != null;
    }

    private Posts getPostWithCache(final Object postId) {
        return getPostDetail(postId);
    }

    private List<Posts> getPostsByIdsWithEnrichment(final List<Object> postIds) {
        final List<Posts> posts = postService.getByIdList(postIds);
        posts.forEach(this::enrichPostInfo);
        return posts;
    }

    private List<Object> convertToObjectList(final List<Integer> integerList) {
        return new ArrayList<>(integerList);
    }

    private String getBatchOperationMessage(final String action) {
        switch (action) {
            case "trash":
                return "批量移至回收站成功";
            case "delete":
                return "批量删除成功";
            case "restore":
                return "批量恢复成功";
            default:
                return "操作成功";
        }
    }

    private String getErrorCode(final String methodName) {
        switch (methodName) {
            case "createPost":
                return ERROR_CREATE_POST_FAILED;
            case "updatePost":
                return ERROR_UPDATE_POST_FAILED;
            case "deletePost":
                return ERROR_DELETE_POST_FAILED;
            case "setSticky":
                return ERROR_SET_STICKY_FAILED;
            default:
                return ERROR_BATCH_OPERATE_FAILED;
        }
    }

    private String getErrorMessage(final String methodName) {
        switch (methodName) {
            case "createPost":
                return "创建文章失败，系统异常";
            case "updatePost":
                return "更新文章失败，系统异常";
            case "deletePost":
                return "删除文章失败，系统异常";
            case "setSticky":
                return "设置置顶状态异常";
            default:
                return "操作失败，系统异常";
        }
    }
}